package utils;

import java.io.UnsupportedEncodingException;
import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.charset.Charset;

public class HexUtil {


    /**
     * 用于建立十六进制字符的输出的小写字符数组
     */
    private static final char[] DIGITS_LOWER = {'0', '1', '2', '3', '4', '5',
            '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};

    /**
     * 用于建立十六进制字符的输出的大写字符数组
     */
    private static final char[] DIGITS_UPPER = {'0', '1', '2', '3', '4', '5',
            '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};

    /**
     * 将字节数组转换为十六进制字符数组
     *
     * @param data byte[]
     * @return 十六进制char[]
     */
    public static char[] encodeHex(byte[] data) {
        return encodeHex(data, true);
    }

    /**
     * 将字节数组转换为十六进制字符数组
     *
     * @param data        byte[]
     * @param toLowerCase <code>true</code> 传换成小写格式 ， <code>false</code> 传换成大写格式
     * @return 十六进制char[]
     */
    public static char[] encodeHex(byte[] data, boolean toLowerCase) {
        return encodeHex(data, toLowerCase ? DIGITS_LOWER : DIGITS_UPPER);
    }

    /**
     * 将字节数组转换为十六进制字符数组
     *
     * @param data     byte[]
     * @param toDigits 用于控制输出的char[]
     * @return 十六进制char[]
     */
    protected static char[] encodeHex(byte[] data, char[] toDigits) {
        int l = data.length;
        char[] out = new char[l << 1];
        // two characters form the hex value.
        for (int i = 0, j = 0; i < l; i++) {
            out[j++] = toDigits[(0xF0 & data[i]) >>> 4];
            out[j++] = toDigits[0x0F & data[i]];
        }
        return out;
    }

    /**
     * 将字节数组转换为十六进制字符串
     *
     * @param data byte[]
     * @return 十六进制String
     */
    public static String encodeHexStr(byte[] data) {
        return encodeHexStr(data, true);
    }

    /**
     * 将字节数组转换为十六进制字符串
     *
     * @param data        byte[]
     * @param toLowerCase <code>true</code> 传换成小写格式 ， <code>false</code> 传换成大写格式
     * @return 十六进制String
     */
    public static String encodeHexStr(byte[] data, boolean toLowerCase) {
        return encodeHexStr(data, toLowerCase ? DIGITS_LOWER : DIGITS_UPPER);
    }

    /**
     * 将字节数组转换为十六进制字符串
     *
     * @param data     byte[]
     * @param toDigits 用于控制输出的char[]
     * @return 十六进制String
     */
    protected static String encodeHexStr(byte[] data, char[] toDigits) {
        return new String(encodeHex(data, toDigits));
    }

    /**
     * 将十六进制字符数组转换为字节数组
     *
     * @param data 十六进制char[]
     * @return byte[]
     * @throws RuntimeException 如果源十六进制字符数组是一个奇怪的长度，将抛出运行时异常
     */
    public static byte[] decodeHex(char[] data) {

        int len = data.length;

        if ((len & 0x01) != 0) {
            throw new RuntimeException("Odd number of characters.");
        }

        byte[] out = new byte[len >> 1];

        // two characters form the hex value.
        for (int i = 0, j = 0; j < len; i++) {
            int f = toDigit(data[j], j) << 4;
            j++;
            f = f | toDigit(data[j], j);
            j++;
            out[i] = (byte) (f & 0xFF);
        }

        return out;
    }

    // char转byte
    private byte[] getBytes(char[] chars) {
        Charset cs = Charset.forName("UTF-8");
        CharBuffer cb = CharBuffer.allocate(chars.length);
        cb.put(chars);
        cb.flip();
        ByteBuffer bb = cs.encode(cb);

        return bb.array();
    }

    // byte转char
    private char[] getChars(byte[] bytes) {
        Charset cs = Charset.forName("UTF-8");
        ByteBuffer bb = ByteBuffer.allocate(bytes.length);
        bb.put(bytes);
        bb.flip();
        CharBuffer cb = cs.decode(bb);

        return cb.array();
    }

    /**
     * 将Hex字符串转换成ASCI字符串
     *
     * @param strHex
     * @return
     * @throws Exception
     */
    public static String HexToAsciSting(String strHex) throws Exception {
        byte[] bytes = StringToBytes(strHex);
        String strAsci = new String(bytes, "GBK");
        return strAsci;
    }

    // public static String HexToAsciiString(String strHex){
    // byte [] bytes = StringToBytes(strHex);
    // String strAsci = "";
    // try {
    // strAsci = new String(bytes,"GBK");
    // } catch (UnsupportedEncodingException e) {
    // strAsci = "";
    // }
    // return strAsci;
    // }
    public static String HexToAsciiString(String strHex) {
        byte[] bytes = StringToBytes(strHex);
        int i = 0;
        for (i = 0; i < bytes.length; i++) {
            if (bytes[i] == 0)
                break;
        }
        String strAsci = "";
        try {
            strAsci = new String(bytes, 0, i, "GBK");
        } catch (UnsupportedEncodingException e) {
            strAsci = "";
        }
        return strAsci;
    }

    /**
     * 将一个ASCI字符串转成HEX字符串
     *
     * @param strAsci
     * @return
     * @throws UnsupportedEncodingException
     */
    public static String AsciToHexString(String strAsci)
            throws UnsupportedEncodingException {
        String s = String.valueOf(strAsci);
        byte[] bytes = s.getBytes("GBK");// e4baac413132333435000000
        // for (int i = 0; i < bytes.length; i++)
        // strHex += Integer.toHexString(bytes[i] & 0xff);
        // strHex.toLowerCase();
        return HexToString(bytes);
    }

    /**
     * 将一个ASCI字符串转成HEX字符串,限定长度
     *
     * @param strAsci
     * @param nLen长度限定 ,不足的补字符0
     * @return
     * @throws UnsupportedEncodingException
     */
    public static String AsciToHexString(String strAsci, int nLen)
            throws UnsupportedEncodingException {
        String s = String.valueOf(strAsci);
        byte[] bytes = s.getBytes("GBK");// e4baac413132333435000000
        String strResult = HexToString(bytes);
        int strLen = strResult.length();
        if (strLen >= nLen)
            strResult = strResult.substring(0, nLen);
        else {
            int nAddLen = nLen - strLen;
            for (int i = 0; i < nAddLen; i++)
                strResult += "0";
        }

        return strResult;
    }

    public static String HexToString(byte[] inHex) {
        int i;
        StringBuilder strResult = new StringBuilder();
        strResult.append("");
        for (i = 0; i < inHex.length; i++) {
            strResult.append(String
                    .valueOf(DIGITS_UPPER[(0xF0 & inHex[i]) >>> 4]));
            strResult.append(String.valueOf(DIGITS_UPPER[inHex[i] & 0x0F]));
        }
        return strResult.toString();
    }

    public static String Bytes2HexString(byte[] b) {
        String ret = "";
        for (int i = 0; i < b.length; i++) {
            String hex = Integer.toHexString(b[i] & 0xFF);
            if (hex.length() == 1) {
                hex = '0' + hex;
            }
            ret += hex.toUpperCase();
        }
        return ret;
    }

    public static String BytesToString(byte[] inHex, int nOff, int nLen) {
        int i;
        StringBuilder strResult = new StringBuilder();
        strResult.append("");
        for (i = 0; i < nLen; i++) {
            strResult.append(String
                    .valueOf(DIGITS_UPPER[(0xF0 & inHex[nOff + i]) >>> 4]));
            strResult.append(String
                    .valueOf(DIGITS_UPPER[inHex[nOff + i] & 0x0F]));
        }
        return strResult.toString();
    }
    public static String asciiToString(String value)
    {
        StringBuffer sbu = new StringBuffer();
        String[] chars = value.split(",");
        for (int i = 0; i < chars.length; i++) {
            sbu.append((char) Integer.parseInt(chars[i]));
        }
        return sbu.toString();
    }

    // 十进制转化为十六进制，结果为C8。
    // Integer.toHexString(200);

    /**
     * 1字节转成2个字符串十六进制字符串
     *
     * @param dec
     * @return
     */
    public static String ByteToString(byte dec) {
        return String.valueOf(DIGITS_UPPER[(0xF0 & dec) >>> 4])
                + String.valueOf(DIGITS_UPPER[dec & 0x0F]);
    }

    public static String ByteToString(int dec) {
        return String.valueOf(DIGITS_UPPER[(0xF0 & dec) >>> 4])
                + String.valueOf(DIGITS_UPPER[dec & 0x0F]);
    }

    // 十六进制转化为十进制，结果140。
    // Integer.parseInt("8C",16);

    /**
     * 2个字符十六进制字符串转成byte
     *
     * @param str
     * @return
     */
    public static byte StringToByte(String str) {
        return (byte) Integer.parseInt(str, 16);
    }

    public static byte[] LongToHex(long inLong, int nLen, int flagOb) {
        int i = 0;
        byte[] outHex = new byte[nLen];
        for (i = 0; i < nLen; i++) {
            if (flagOb != 0)
                outHex[nLen - 1 - i] = (byte) (inLong >> (8 * (nLen - 1 - i)));
            else
                outHex[i] = (byte) (inLong >> (8 * (nLen - 1 - i)));
        }
        return outHex;

    }

    /**
     * 整数转成十六进制格式字符串
     */
    public static String LongToHexString(long inLong, int nLen, int flagOb) {
        return HexToString(LongToHex(inLong, nLen, flagOb));
    }

    /**
     * 十六进制格式字符串转成整数
     *
     * @param hexstr 最多8个字符
     * @return
     */
    public static long HexStringToLong(String hexstr) {
        int nlen = hexstr.length() / 2;
        long lResult = 0;
        long lTmp;
        byte byteTmp;
        for (int i = 0; i < nlen; i++) {
            byteTmp = StringToByte(hexstr.substring(i * 2, (i + 1) * 2));
            lTmp = (byteTmp & 0xFF) << (nlen - i - 1) * 8;
            lResult += lTmp;
        }
        return lResult;
    }

    /**
     * 整形字符串转成十六进制字符串
     *
     * @param str
     * @param nLimitLen 转换后字符的长度,必须是2的整数倍
     * @return
     */
    public static String IntStringToHexString(String str, int nLimitLen) {
        int nValue = Integer.parseInt(str);
        int nLen = nLimitLen / 2;
        byte[] hexs = LongToHex(nValue, nLen, 0);
        String strResult = HexToString(hexs);
        return strResult;
    }

    /**
     * 将字符串转成byte[]
     *
     * @param str
     * @return
     */
    public static byte[] StringToBytes(String str) {
        int nLen = str.length();
        byte bytes[] = new byte[str.length() / 2];
        for (int i = 0; i < nLen / 2; i++) {
            bytes[i] = StringToByte(str.substring(i * 2, i * 2 + 2));
        }
        return bytes;
    }

    /**
     * 将字符串补80后转成byte[]
     *
     * @param str
     * @return
     */
    public static byte[] StringToBytes80(String str, int flagMac) {
        String str80 = str;
        int nLen = str.length();
        int add80Len = 8;

        if ((nLen / 2 % 8) != 0)
            add80Len = 8 - (nLen / 2 % 8);
        if (flagMac == 0) {
            if ((add80Len == 8))
                add80Len = 0;
        }

        for (int i = 0; i < add80Len; i++) {
            if (i == 0)
                str80 += "80";
            else
                str80 += "00";
        }
        nLen = str80.length() / 2;
        byte bytes[] = new byte[nLen];
        for (int i = 0; i < nLen; i++) {
            bytes[i] = StringToByte(str80.substring(i * 2, i * 2 + 2));
        }
        return bytes;
    }

    public static String StringApp80(String str, int flagMac) {
        String str80 = str;
        int nLen = str.length();
        int add80Len = 8;
        if ((nLen / 2 % 8) != 0)
            add80Len = 8 - (nLen / 2 % 8);
        if (flagMac == 0) {
            if ((add80Len == 8))
                add80Len = 0;
        }
        for (int i = 0; i < add80Len; i++) {
            if (i == 0)
                str80 += "80";
            else
                str80 += "00";
        }
        return str80;
    }

    /**
     * 计算3DESMAC
     *
     * @param Rand
     * @param Key
     * @param Value
     * @return
     */
//	public static String CalDesMac(String Rand, String Key, String Value) {
//		String strMac = new String();
//		strMac = "";
//		byte[] byteRand;
//		byteRand = StringToBytes(Rand.substring(0, 16));
//		byte[] byteKey;
//		byteKey = StringToBytes(Key.substring(0, 32));
//		byte[] byteValue;
//		byteValue = StringToBytes80(Value, 1);
//		byte[] bytesResult;
//		bytesResult = desmac.CalDesMac(byteRand, byteKey, byteValue);
//		strMac = HexToString(bytesResult);
//		return strMac;
//	}

    /**
     * IDEA加密数据
     *
     * @param Key
     * @param Value
     * @return
     */


    /**
     * DES解密
     *
     * @param Key
     * @param Value
     * @return
     */
//	public static String jiemi(String mingwen) {
//		String key = "00000000000000000000000000000000";
//		String strResult = new String();
//		strResult = "";
//		byte[] byteKey;
//		byteKey = StringToBytes(key.substring(0, 32));
//		byte[] byteValue;
//		byteValue = StringToBytes80(mingwen, 0);
//		byte[] bytesResult;
//		byte[] de3Des = desmac.De3Des(byteKey, byteValue);
//		strResult = HexToString(de3Des);
//		return strResult;
//
//	}

    /**
     * DES加密
     *
     * @param Key
     * @param Value
     * @return
     */
//	public static String Encoding3Des(String Key, String Value) {
//		String strResult = new String();
//		strResult = "";
//		byte[] byteKey;
//		byteKey = StringToBytes(Key.substring(0, 32));
//		byte[] byteValue;
//		byteValue = StringToBytes80(Value, 0);
//		byte[] bytesResult;
//		bytesResult = desmac.En3Des(byteKey, byteValue);
//		strResult = HexToString(bytesResult);
//		return strResult;
//	}

    /**
     * 生成指纹码
     *
     * @param Rand
     * @param SessionKey
     * @param Value
     * @return
     */
//	public static String CalFingerprintKey(String Rand, String SessionKey,
//			String Value) {
//		Log.i("test", Value);
//		// String Result = HexUtil.EncodingIdea(SessionKey, Value);
//		String Result = HexUtil.Encoding3Des(SessionKey, Value);
//		Log.i("计算IDEA:", Result);
//		String macResult = HexUtil.CalDesMac(Rand, SessionKey.substring(8, 40),
//				Result);
//		Log.i("计算MAC:", macResult);
//		return macResult;
//	}

//	public static String CalCrc(String Value) {
//		char usIniCrc = 0x5075;
//		char usResult;
//
//		byte[] byteValue;
//		byteValue = StringToBytes(Value);
//
//		usResult = desmac.GetCrc(usIniCrc, byteValue);
//		String strResult = HexToString(LongToHex(usResult, 2, 0));
//		return strResult;
//	}

    /**
     * 产生字节随机数
     *
     * @param numByte 字节个数
     * @return
     */
    public static String GetRand(int numByte) {
        // (int)(Math.Random()*n)
        String strRandom = new String();
        strRandom = "";
        for (byte i = 0; i < numByte; i++)
            strRandom += ByteToString((byte) ((int) (Math.random() * 255)));
        return strRandom;
    }

    /**
     * 将十六进制字符转换成一个整数
     *
     * @param ch    十六进制char
     * @param index 十六进制字符在字符数组中的位置
     * @return 一个整数
     * @throws RuntimeException 当ch不是一个合法的十六进制字符时，抛出运行时异常
     */
    protected static int toDigit(char ch, int index) {
        int digit = Character.digit(ch, 16);
        if (digit == -1) {
            throw new RuntimeException("Illegal hexadecimal character " + ch
                    + " at index " + index);
        }
        return digit;
    }

    void f_buff_xor(byte[] buf1, byte[] buf2, int i_len) {
        int i;
        for (i = 0; i < i_len; i++) {
            buf1[i] = (byte) (buf1[i] ^ buf2[i]);
        }
    }

    public static void main(String[] args) {
        String srcStr = "待转换字符串";
        String encodeStr = encodeHexStr(srcStr.getBytes());
        String decodeStr = new String(decodeHex(encodeStr.toCharArray()));
        System.out.println("转换前：" + srcStr);
        System.out.println("转换后：" + encodeStr);
        System.out.println("还原后：" + decodeStr);
    }

    public String strHello;

    public String hello(String str) {
        String strTmp = new String();
        strTmp = strHello + str;
        return strTmp;
    }

    public void hello2(String str) {
        strHello = str;
    }

    /**
     * 计算bcd值
     *
     * @param asc
     * @return
     */
    public static byte[] str2Bcd(String asc) {
        int len = asc.length();
        int mod = len % 2;
        if (mod != 0) {
            asc = "0" + asc;
            len = asc.length();
        }
        byte abt[] = new byte[len];
        if (len >= 2) {
            len = len / 2;
        }
        byte bbt[] = new byte[len];
        abt = asc.getBytes();
        int j, k;
        for (int p = 0; p < asc.length() / 2; p++) {
            if ((abt[2 * p] >= '0') && (abt[2 * p] <= '9')) {
                j = abt[2 * p] - '0';
            } else if ((abt[2 * p] >= 'a') && (abt[2 * p] <= 'z')) {
                j = abt[2 * p] - 'a' + 0x0a;
            } else {
                j = abt[2 * p] - 'A' + 0x0a;
            }
            if ((abt[2 * p + 1] >= '0') && (abt[2 * p + 1] <= '9')) {
                k = abt[2 * p + 1] - '0';
            } else if ((abt[2 * p + 1] >= 'a') && (abt[2 * p + 1] <= 'z')) {
                k = abt[2 * p + 1] - 'a' + 0x0a;
            } else {
                k = abt[2 * p + 1] - 'A' + 0x0a;
            }
            int a = (j << 4) + k;
            byte b = (byte) a;
            bbt[p] = b;
        }
        return bbt;
    }
}
